#include "fxcc/core/graph/common/ImageMipmap.h"
#include "fxcc/core/Dir.h"

#include "stb_image.h"
#include "stb_image_write.h"
#include "stb_image_resize2.h"

void fxcc::graph::common::ImageMipmap::MipMapData::SaveBMP(const std::string& bmpPath) const
{
    if (!m_HDR)
        stbi_write_bmp(bmpPath.c_str(), m_Width, m_Height, m_NrComponent, (const void*)GetData());
}

void fxcc::graph::common::ImageMipmap::MipMapData::SaveHDR(const std::string& path)const
{
    fxcc::FileUtil::CreateParentDirs(path);

    if (m_HDR)
    {
        stbi_write_hdr(path.c_str(), m_Width, m_Height, m_NrComponent, m_Floats.data());
    }
};



bool fxcc::graph::common::ImageMipmap::MipMapData::DrawRect(const MipMapData& sourceImage, const glm::ivec2& numSep, const glm::ivec2& pos)
{
    int w = sourceImage.m_Width;
    int h = sourceImage.m_Height;

    int outW = m_Width;
    int outH = m_Height;

    for (int y = 0; y < h; ++y) {
        for (int x = 0; x < w; ++x) {
            int dstX = pos.x * w + x;
            int dstY = pos.y * h + y;
            int dstIdx = (dstY * outW + dstX) * m_NrComponent;
            int srcIdx = (y * w + x) * m_NrComponent;
            std::memcpy(&m_Data[dstIdx], &sourceImage.m_Data[srcIdx], m_NrComponent);
        }
    }

    return true;
}

std::string fxcc::graph::common::ImageMipmap::MipMapData::SaveImage(const std::string& pathnoSuffix) const
{
    std::string realPath;
    if (m_HDR)
    {
        realPath = pathnoSuffix + ".hdr";
        SaveHDR(realPath);
    }
    else
    {
        realPath = pathnoSuffix + ".bmp";
        SaveBMP(realPath);
    }
    return realPath;
}

fxcc::graph::common::ImageMipmap::ImageMipmap()
{
}

fxcc::graph::common::ImageMipmap::ImageMipmap(const Desc& desc)
    :m_Desc(desc)
{
    m_Available = Init();
}

fxcc::graph::common::ImageMipmap::~ImageMipmap()
{
}
int fxcc::graph::common::ImageMipmap::NumBitOfPixel() const
{
    return m_WICTexture.NumBitOfPixel();
}

int fxcc::graph::common::ImageMipmap::RowPitch() const
{
    return  m_WICTexture.RowPitch();
}

bool fxcc::graph::common::ImageMipmap::Init()
{

    return InitWIC();
}

bool fxcc::graph::common::ImageMipmap::InitWIC()
{
    MipMapData& levelData = m_WICTexture;

    if (m_Desc.m_WICFlipY)
    {
        stbi_set_flip_vertically_on_load(true);
    }
    void* m_Data = 0;
    if (m_Desc.m_wicHdr)
    {
        m_Data = stbi_loadf(m_Desc.m_wicPath.c_str(), &levelData.m_Width, &levelData.m_Height, &levelData.m_NrComponent, m_Desc.m_wicReq);
    }
    else
    {
        m_Data = stbi_load(m_Desc.m_wicPath.c_str(), &levelData.m_Width, &levelData.m_Height, &levelData.m_NrComponent, m_Desc.m_wicReq);
    };

    if (m_Data)
    {
        levelData.m_HDR = m_Desc.m_wicHdr;

        if (m_Desc.m_wicReq)
        {
            levelData.m_NrComponent = m_Desc.m_wicReq;
        }
        if (levelData.m_HDR)
        {
            levelData.AllocFloat((float*)m_Data);
        }
        else
        {
            levelData.AllocUINT8((unsigned char*)m_Data);

        }

        stbi_image_free(m_Data);
    }


    if (m_Desc.m_WICFlipY)
    {
        stbi_set_flip_vertically_on_load(false);
    }
    return m_Data;
}